package Statistics;

/**
 * Keep track of a single stat.
 * @author Hetalar
 * 07/02/2012 
 */
public abstract class Stat
{
	protected double value;
	//Reference to the statistic this stat belongs to 
	//Required for allowing access to the other stats.
	protected Statistics statistic;
	protected String name;
	protected int id;
	
	protected static final int MINIMUM_STAT_VALUE = 0;
	protected static final int MAXIMUM_STAT_VALUE = 255;
	
	/**
	 * Constructor for Stat
	 * @param value Initial Value of the stat
	 * @param name Name of the stat
	 */
	protected Stat(Statistics stat, int value, String name, int id)
	{
		this.statistic = stat;
		this.name = name;
		this.value = value;
		this.id = id;
	}
	
	/**
	 * Overloaded Constructor, initializes a blank Stat
	 */
	protected Stat(Statistics stat)
	{
		this(stat, 0, "", -1);
	}
	
	/**
	 * Sets the value stored within the stat
	 * @param value new value of the stat
	 */
	public void setValue(double value)
	{
		double oldVal = this.value;
		if(checkWithinRange(value))
		{
			this.value = value;
		}
		applyStat(oldVal);
	}
	
	/**
	 * Gets the value stored within this stat
	 */
	public double getValue()
	{
		return this.value;
	}
	
	/**
	 * Increases the stat by the amount specified
	 * @param howMuch Number to increase the stat by
	 */
	public void increaseValue(double howMuch)
	{
		double oldVal = this.value;
		double newValue =  this.value + howMuch;
		if(checkWithinRange(newValue))
		{
			setValue(newValue);
		}
		applyStat(oldVal);
	}
	
	
	/**
	 * Needs to be overwritten in the child classes.
	 * @param oldValue Value that used to be in the stat.
	 */
	protected void applyStat(double oldValue)
	{
		//Checks if the stat is the primary
		if(this.statistic.getPrimaryStat() == this.id)
		{
			double change = oldValue - this.statistic.getStatValue(this.statistic.getPrimaryStat());
																						
			if(change != 0)
			{
				this.statistic.increaseStat(Statistics.STAT_ATK_POWER, 
						Coefficients.calcAPChange(change, statistic));
			}
		}
	}
	
	/**
	 * Decreases the stat by the amount specified
	 * @param howMuch Number to decrease the stat by
	 */
	public void decreaseValue(double howMuch)
	{
		double oldVal = this.value;
		double newValue =  this.value - howMuch;
		if(checkWithinRange(newValue))
		{
			setValue(newValue);
		}
		applyStat(oldVal);
	}
	
	/**
	 * Checks to see if the value is within the min and max range
	 * @param value to check
	 * @return true if it is, false if it isn't
	 */
	private boolean checkWithinRange(double value)
	{
		return value >= MINIMUM_STAT_VALUE && value <= MAXIMUM_STAT_VALUE;
	}
}
